// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: wsfuyibing <682805@qq.com>
// Date: 2025-02-13

package sell_refund

import (
    "context"
    "integration/app/errs"
    "integration/app/lib/conf"
    "integration/app/models"
    "integration/app/services"
    "time"
)

// Order
// 订单信息.
type Order struct {
    Account        int           `json:"account" label:"结算账户ID"`
    Actual         float64       `json:"actual" label:"实际金额" desc:"所有商品的价税合计总和"`
    Amount         float64       `json:"amount" label:"结算金额"`
    Check          int           `json:"check" label:"核对状态"`
    Cost           float64       `json:"cost" label:"单据费用"`
    Cse            float64       `json:"cse" label:"费用状态"`
    Customer       int           `json:"customer" label:"客户ID"`
    Data           string        `json:"data" label:"备注"`
    Discount       float64       `json:"discount" label:"优惠金额"`
    Examine        bool          `json:"examine" label:"审核状态"`
    Field          OrderField    `json:"field" label:"扩展字段"`
    File           []any         `json:"file" label:"附件信息"`
    OrganizationId int           `json:"frame" label:"组织结构ID"`
    Id             int           `json:"id" label:"单据ID"`
    Invoice        int           `json:"invoice" label:"发票状态"`
    Logistic       OrderLogistic `json:"logistic" label:"物流状态"`
    Money          float64       `json:"money" label:"实付金额"`
    Nucleus        int           `json:"nucleus" label:"结算状态"`
    Number         string        `json:"number" label:"单据编号"`
    ManagerId      int           `json:"person" label:"制单人"`
    Time           string        `json:"time" label:"制单时间"`
    Total          float64       `json:"total" label:"价税合计"`
    CreatorId      int           `json:"user" label:"制单人ID"`
}

func NewOrder() *Order {
    return &Order{
        File: make([]any, 0),
    }
}

func (o *Order) With(ctx context.Context, agent *conf.ErpAgent, order *models.Order, goods []*Goods) (err error) {
    if err = o.loadHistory(ctx, agent, order); err == nil {
        if err = o.loadCustomer(ctx, agent, order); err == nil {
            o.loadAgent(agent)
            o.loadSum(goods)
            o.loadDefaulter()
        }
    }
    return
}

func (o *Order) loadDefaulter() {
    o.Cse = 3
    o.Nucleus = 2
    o.Logistic.Key = "auto"
}

func (o *Order) loadAgent(agent *conf.ErpAgent) {
    o.Account = agent.CoinAccountId
    o.CreatorId = agent.CreatorId
    o.OrganizationId = agent.OrganizationId
    o.ManagerId = agent.ManagerId
}

func (o *Order) loadCustomer(ctx context.Context, agent *conf.ErpAgent, order *models.Order) (err error) {
    var bean *models.ErpCustomer
    if bean, err = services.NewErpCustomerService().GetByErpNumber(ctx, agent.GenerateCustomerNo(order.Uid)); err != nil {
        err = errs.ErrDatabaseQueryFailed
        return
    }
    if bean == nil {
        err = errs.ErrErpCustomerNotSync
        return
    }
    o.Customer = bean.ErpId
    return
}

func (o *Order) loadHistory(ctx context.Context, agent *conf.ErpAgent, order *models.Order) (err error) {
    var (
        bean    *models.ErpRefund
        service = services.NewErpRefundService()
    )

    // 1. 查询历史.
    if bean, err = service.GetByOrderId(ctx, order.Id); err != nil {
        return
    }

    // 2. 复用历史.
    if bean != nil {
        o.Id = bean.OutId
        o.Number = bean.OutTradeNo
        o.Time = bean.OutDate
        return
    }

    // 3. 创建历史.
    model := &models.ErpRefund{
        OrderId:    order.Id,
        OrderNo:    order.OrderId,
        OutDate:    time.Now().Add(time.Hour * 24).Format(time.DateOnly),
        OutTradeNo: agent.GenerateOutRefundNo(order.Id),
    }
    if bean, err = service.Add(ctx, model); err == nil {
        o.Number = bean.OutTradeNo
        o.Time = bean.OutDate
    }
    return
}

func (o *Order) loadSum(goods []*Goods) {
    for _, item := range goods {
        o.Amount += item.TaxTotal
    }
    o.Actual = o.Amount
    o.Money = o.Amount
    o.Total = o.Amount
}
